package com.wz.utils.concurrency.synchronizedlock;

import org.openjdk.jol.info.ClassLayout;

import java.io.IOException;

/**
 * @Author : Wang Zhen.
 * @Date : Created in 10:24 2022/11/5
 * @Description :
 * @Modified By   :
 * @Version :
 */
public class SyncBias {
    public static void main(String[] args) throws InterruptedException {
//        // 偏向锁延迟，轻量级锁00
//        testBias1();
//        // 跳过偏向锁延迟,偏向锁101
//        testBias2();
//        // 锁Class对象，轻量级锁00
//        testBias3();
//        // hashCode()，偏向锁撤销，轻量级锁00
        testBias4();
//        // 锁内部调用hashCode()，偏向锁撤销，重量级锁10
//        testBias5();
//        // 锁内部调用obj.notify()，偏向锁撤销，轻量级锁00
//        testBias6();
//        // 锁内部调用obj.wait()，偏向锁撤销，轻量级锁10
        // wait是monitor机制实现的，一定要生成ObjectMonitor对象
//        testBias7();
        // 偏向锁，但是偏向的线程id未改变（可能原因：线程完结后，被复用）
//        testBias8();
        // 偏向锁，保活，第二个变为轻量级锁
//        testBias9();
    }


    public static void testBias1() throws InterruptedException {

        Object obj = new Object();
        //查看对象内部信息
        System.out.println(ClassLayout.parseInstance(obj).toPrintable());

        // 偏向锁延迟
        new Thread(() -> {
            synchronized (obj) {
                System.out.println(Thread.currentThread().getName() + "\n"
                        + ClassLayout.parseInstance(obj).toPrintable());
            }
        }, "Thread1").start();
    }

    public static void testBias2() throws InterruptedException {
        // 跳过4s的偏向锁延迟
        Thread.sleep(5000);
        Object obj = new Object();
        //查看对象内部信息
        System.out.println(ClassLayout.parseInstance(obj).toPrintable());

        // 偏向锁延迟
        new Thread(() -> {
            synchronized (obj) {
                System.out.println(Thread.currentThread().getName() + "\n"
                        + ClassLayout.parseInstance(obj).toPrintable());
            }
        }, "Thread2").start();
    }


    public static void testBias3() throws InterruptedException {
        // 跳过4s的偏向锁延迟
        Thread.sleep(5000);
        Object obj = new Object();
        //查看对象内部信息
        System.out.println(ClassLayout.parseInstance(obj).toPrintable());

        // 偏向锁延迟
        new Thread(() -> {
            synchronized (SyncBias.class) {
                System.out.println(Thread.currentThread().getName() + "\n"
                        + ClassLayout.parseInstance(SyncBias.class).toPrintable());
            }
        }, "Thread3").start();
    }

    public static void testBias4() throws InterruptedException {
        // 跳过4s的偏向锁延迟
        Thread.sleep(5000);
        Object obj = new Object();
        obj.hashCode();
        //查看对象内部信息
        System.out.println(ClassLayout.parseInstance(obj).toPrintable());

        // 偏向锁延迟
        new Thread(() -> {
            synchronized (obj) {
                synchronized (obj) {
                    System.out.println(Thread.currentThread().getName() + "\n"
                            + ClassLayout.parseInstance(obj).toPrintable());
                }
            }
        }, "Thread4").start();
    }

    public static void testBias5() throws InterruptedException {
        // 跳过4s的偏向锁延迟
        Thread.sleep(5000);
        Object obj = new Object();

        //查看对象内部信息
        System.out.println(ClassLayout.parseInstance(obj).toPrintable());

        // 偏向锁延迟
        new Thread(() -> {
            synchronized (obj) {
                // TODO 为啥会变为重量级锁？
                obj.hashCode();

                System.out.println(Thread.currentThread().getName() + "\n"
                        + ClassLayout.parseInstance(obj).toPrintable());
            }
        }, "Thread5").start();
    }

    public static void testBias6() throws InterruptedException {
        // 跳过4s的偏向锁延迟
        Thread.sleep(5000);
        Object obj = new Object();

        //查看对象内部信息
        System.out.println(ClassLayout.parseInstance(obj).toPrintable());

        // 偏向锁延迟
        new Thread(() -> {
            synchronized (obj) {
                obj.notify();

                System.out.println(Thread.currentThread().getName() + "\n"
                        + ClassLayout.parseInstance(obj).toPrintable());
            }
        }, "Thread6").start();
    }

    public static void testBias7() throws InterruptedException {
        // 跳过4s的偏向锁延迟
        Thread.sleep(5000);
        Object obj = new Object();

        //查看对象内部信息
        System.out.println(ClassLayout.parseInstance(obj).toPrintable());

        // 偏向锁延迟
        new Thread(() -> {
            synchronized (obj) {
                try {
                    obj.wait(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                System.out.println(Thread.currentThread().getName() + "\n"
                        + ClassLayout.parseInstance(obj).toPrintable());
            }
        }, "Thread7").start();
    }

    public static void testBias8() throws InterruptedException {
        // 跳过4s的偏向锁延迟
        Thread.sleep(5000);
        Object obj = new Object();

        //查看对象内部信息
        System.out.println(ClassLayout.parseInstance(obj).toPrintable());


        new Thread(() -> {
            synchronized (obj) {
                System.out.println(Thread.currentThread().getName() + "\n"
                        + ClassLayout.parseInstance(obj).toPrintable());
            }
        }, "Thread8").start();

        Thread.sleep(1000);

        new Thread(() -> {
            synchronized (obj) {
                System.out.println(Thread.currentThread().getName() + "\n"
                        + ClassLayout.parseInstance(obj).toPrintable());
            }
        }, "Thread9").start();
    }


    public static void testBias9() throws InterruptedException {
        // 跳过4s的偏向锁延迟
        Thread.sleep(5000);
        Object obj = new Object();

        //查看对象内部信息
        System.out.println(ClassLayout.parseInstance(obj).toPrintable());


        new Thread(() -> {
            synchronized (obj) {
                System.out.println(Thread.currentThread().getName() + "\n"
                        + ClassLayout.parseInstance(obj).toPrintable());
            }

            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "Thread10").start();

        Thread.sleep(1000);

        new Thread(() -> {
            synchronized (obj) {
                System.out.println(Thread.currentThread().getName() + "\n"
                        + ClassLayout.parseInstance(obj).toPrintable());
            }
        }, "Thread11").start();
    }
}
